package by.imotaeva.printing_services.dataaccess.impl;

import java.util.List;

import javax.persistence.Query;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

import org.apache.commons.lang3.Validate;
import org.springframework.stereotype.Repository;

import by.imotaeva.printing_services.dataaccess.PrintingProductOrderDao;
import by.imotaeva.printing_services.datamodel.Customer;
import by.imotaeva.printing_services.datamodel.OrderStatus;
import by.imotaeva.printing_services.datamodel.PrintingProductOrder;
import by.imotaeva.printing_services.datamodel.PrintingProductOrder_;

@Repository
public class PrintingProductOrderDaoImpl extends AbstractDaoImpl<Long, PrintingProductOrder> implements
		PrintingProductOrderDao {

	protected PrintingProductOrderDaoImpl() {
		super(PrintingProductOrder.class);
	}

	@Override
	public void deletePrintingProductOrder(List<Long> ids) {
		if (ids.isEmpty()) {
			// todo warning
		} else {
			// Validate.notEmpty(ids, "collection should never be empty");
			String q = String.format("delete from %s e where e.id in (:ids)",
					PrintingProductOrder.class.getSimpleName());
			Query updateQuery = getEm().createQuery(q);
			updateQuery.setParameter("ids", ids);
			updateQuery.executeUpdate();
		}
	}

	@Override
	public OrderStatus getStatusByProductionOrderNum(Long number) {
		CriteriaBuilder cBuilder = getEm().getCriteriaBuilder();

		CriteriaQuery<OrderStatus> criteria = cBuilder.createQuery(OrderStatus.class);
		Root<PrintingProductOrder> root = criteria.from(PrintingProductOrder.class);

		criteria.select(root.get(PrintingProductOrder_.productionOrderStatus));
		criteria.where(cBuilder.equal(root.get(PrintingProductOrder_.productionOrderNumber), number));

		TypedQuery<OrderStatus> query = getEm().createQuery(criteria);
		OrderStatus result = query.getSingleResult();
		return result;
	}

	@Override
	public Customer getCustomerByProductionOrderNum(Long number) {
		CriteriaBuilder cBuilder = getEm().getCriteriaBuilder();

		CriteriaQuery<Customer> criteria = cBuilder.createQuery(Customer.class);
		Root<PrintingProductOrder> root = criteria.from(PrintingProductOrder.class);

		criteria.select(root.get(PrintingProductOrder_.customer));
		root.fetch(PrintingProductOrder_.customer);
		criteria.where(cBuilder.equal(root.get(PrintingProductOrder_.productionOrderNumber), number));

		TypedQuery<Customer> query = getEm().createQuery(criteria);
		Customer result = query.getSingleResult();
		return result;
	}

	@Override
	public void updateProductStatus(Long orderNumber, OrderStatus newStatus) {
		String q = String
				.format("update from %s p set p.productionOrderStatus=:newNameParam where p.productionOrderNumber=:orderNumber",
						PrintingProductOrder.class.getSimpleName());
		Query updateQuery = getEm().createQuery(q);
		updateQuery.setParameter("newNameParam", newStatus);
		updateQuery.setParameter("orderNumber", orderNumber);
		int updatedRowsCount = updateQuery.executeUpdate();
		Validate.isTrue(updatedRowsCount == 1, "One row should be updated");
	}

	@Override
	public Long getCount() {
		CriteriaBuilder cBuilder = getEm().getCriteriaBuilder();

		CriteriaQuery<Long> criteria = cBuilder.createQuery(Long.class);
		Root<PrintingProductOrder> root = criteria.from(PrintingProductOrder.class);

		criteria.select(cBuilder.count(root));

		TypedQuery<Long> query = getEm().createQuery(criteria);
		return query.getSingleResult();
	}

}
